home *** CD-ROM | disk | FTP | other *** search
- page
- ;***********************************************************
- ;** **
- ;** Device Driver for RS232 communications **
- ;** Copyright (C) Texas Instruments 1986 **
- ;** Author: Greg Haley **
- ;** **
- ;** THIS SOURCE CODE MAY BE DISTRIBUTED AND MODIFIED **
- ;** ONLY IF THE ORIGINAL COPYRIGHT AND AUTHOR CREDITS **
- ;** REMAIN INTACT. **
- ;** **
- ;** Project Start Date: 09/09/86 **
- ;** **
- ;** Re: 10/14/86 by Greg Haley **
- ;** Added more delays (jmp $+2) for more tolerant **
- ;** timing. Also increased stacks to 80 words for **
- ;** Business Pro compatibility. **
- ;** **
- ;** Re: 10/15/86 by Greg Haley **
- ;** The COMM chip is no longer initialized on every **
- ;** write request. **
- ;** **
- ;** Re: 10/23/86 by Greg Haley **
- ;** Added code to block interrupts while setting up **
- ;** and restoring the stack. **
- ;** **
- ;** Re: 11/07/86 by Greg Haley **
- ;** Added option to echo RS232 I/O to the CRT. **
- ;** **
- ;** Re: 11/13/86 by Greg Haley **
- ;** Save SI and AX when calling DOS fast write. **
- ;** Changed SAR's and SAL's to SHR's and SHL's. **
- ;** Added keyboard input in parallel with RS232 input. **
- ;** **
- ;** Re: 11/20/86 by Greg Haley **
- ;** Modified I/O channel commands so that a more **
- ;** standard structure could be used, and to make it **
- ;** easier to add new commands in the future. Also, **
- ;** all machine dependent code was moved to a seperate **
- ;** file to allow new machines to be added much more **
- ;** easily. **
- ;** **
- ;** Re: 12/29/86 by Greg Haley **
- ;** Fixed bug in XON-XOFF busy handling where XON **
- ;** was not sent to reset the busy condition. **
- ;** **
- ;***********************************************************
-
- cr equ 13
- lf equ 10
- fast_write equ 29h ; DOS INT for fast CRT write
-
- com1_tbl: ;header for device
- dw -1
- dw -1
- dw 1100000000000000B ; CHAR device with I/O control
- dw strategy
- dw entry
- db 'AUX ' ; Device name to use
-
- ; command jump table
- cmdtbl:
- dw init
- dw exit
- dw exit
- dw ioctl_in
- dw read
- dw nd_read
- dw input_status
- dw input_flush
- dw write
- dw write
- dw output_status
- dw exit
- dw ioctl_out
- dw exit
- dw exit
- dw exit
- dw exit
-
- oldss dw 0 ; Old SS reg
- oldsp dw 0 ; Old SP reg
- dw 80 dup (?) ; New stack
- e_stack label word
- ptrsav dd 0 ; DOS cmd block pointer
- init_once db 0 ; flag for init
- echo_in db 0 ; Echo input to console flag
- echo_out db 0 ; Echo output to console flag
- key_in db 0 ; Parallel keyboard input flag
- dcw_len db 0 ; DCW (0) or Length (not 0) mode
-
- page
- ;***********************************************************
- ;** Device Driver Entry **
- ;***********************************************************
- cmdlen = 0 ;length of this command
- unit = 1 ;sub unit specifier
- cmd = 2 ;command code
- status = 3 ;status
- media = 13 ;media descriptor
- trans = 14 ;transfer address
- count = 18 ;count of blocks or characters
- start = 20 ;first block to transfer
-
- ;***********************************************************
- ;** Strategy Routine **
- ;***********************************************************
- stratp proc far
-
- strategy:
- mov word ptr cs:[ptrsav],bx
- mov word ptr cs:[ptrsav+2],es
- ret
-
- stratp endp
-
- ;***********************************************************
- ;** Entry Routine **
- ;***********************************************************
- entry:
- cli ; disable ints
- mov cs:word ptr oldss,ss
- mov cs:word ptr oldsp,sp
- mov sp,cs
- mov ss,sp
- mov sp,offset e_stack
- sti ; enable ints
- push si
- push ax
- push cx
- push dx
- push di
- push bp
- push ds
- push es
- push bx
-
- lds bx,cs:[ptrsav] ;get pointer to i/o packet
-
- mov cx,word ptr ds:[bx].count ;cx = count
-
- mov al,byte ptr ds:[bx].cmd ; al = command
- cbw
- mov si,offset cmdtbl
- add si,ax
- add si,ax
- cmp al,16
- ja cmderr
-
- les di,dword ptr ds:[bx].trans
-
- push cs
- pop ds
- cld
-
- assume ds:code
-
- jmp word ptr [si] ;go do command
-
- page
- ;***********************************************************
- ;** Device Driver Exit **
- ;***********************************************************
- bus$exit: ;device busy exit
- mov ah,00000011b
- jmp short done
-
- cmderr:
- mov al,3 ;unknown command error
-
- err$exit:
- mov ah,10000001b ;mark error return
- jmp short done
-
- exitp proc far
-
- exit:
- mov ax,0000000100000000b
- done:
- lds bx,cs:[ptrsav]
- mov word ptr [bx].status,ax ;mark operation complete
-
- pop bx
- pop es
- pop ds
- pop bp
- pop di
- pop dx
- pop cx
- pop ax
- pop si
-
- ; restore stack
- cli ; disable ints
- mov ss,cs:word ptr oldss
- mov sp,cs:word ptr oldsp
- sti ; enable ints
-
- ret ;restore regs and return
- exitp endp
-
- page
- ;***********************************************************
- ;** Write Routine **
- ;** **
- ;** ES:DI contain xfer adrs on entry **
- ;** CX contains num chars to write **
- ;** **
- ;** **
- ;***********************************************************
- write proc near
- push es ; Move pointer to DS:SI
- pop ds
- mov si,di
-
- mov dx,cs:word ptr send_buffer ; xmit port
-
- send_chars:
- lodsb ; al now has char
-
- cmp cs:byte ptr echo_out,0 ; Echo output on?
- jz no_echo_out ; No, skip
- push si
- push ax
- int fast_write ; Yes, echo to console
- pop ax
- pop si
- no_echo_out:
-
- write_1:
- cmp cs:byte ptr t_busy,0 ; Is device busy?
- jne write_1 ; Yes, loop again
- x_busy:
- cmp cs:byte ptr xmit_busy,0 ; Is transmitter busy?
- jne x_busy ; Yes, wait for it
- out dx,al
- mov cs:byte ptr xmit_busy,1 ; We're busy now
- loop send_chars ; look for more chars
-
- jmp exit
- write endp
-
- page
- ;***********************************************************
- ;** Non Destructive Read Routine **
- ;** **
- ;** On entry, ES points to buffer segment **
- ;***********************************************************
- nd_read proc near
- mov di,13 ; point to byte buffer
-
- cmp cs:byte ptr key_in,0 ; Look for keyboard input?
- jz nd_read_0 ; No, skip
-
- push cx
- push di
- call k_ready ; Is a char waiting?
- pop di
- pop cx
- jz nd_read_0 ; No, skip
-
- stosb ; Yes, store it
- jmp exit ; We're done
-
- nd_read_0:
- cmp cs:word ptr rq_len,0 ; Any chars in receive buffer?
- jnz nd_read_1 ; Yes, continue
- mov ah,00000011b ; Set busy & done
- jmp done ; We're done
-
- nd_read_1:
- mov bx,offset rqueue ; Get queue ptr
- mov dx,cs:word ptr rq_tail
- add bx,dx ; point at char
- mov al,byte ptr[bx] ; al now has char
-
- cmp cs:byte ptr echo_in,0 ; Echo input on?
- jz no_echo_in ; No, skip
- push si
- push ax
- int fast_write ; Yes, echo to console
- pop ax
- pop si
- no_echo_in:
-
- stosb ; store char in buffer
- jmp exit
- nd_read endp
-
- page
- ;***********************************************************
- ;** Get Input Status **
- ;***********************************************************
- input_status proc near
- cmp cs:byte ptr key_in,0 ; Look for keyboard input?
- jz in_stat_0 ; No, skip
-
- call k_ready ; Is a char waiting?
- jnz xit_in_stat ; Yes, exit
-
- in_stat_0:
- cmp cs:word ptr rq_len,0 ; Any chars in receive buffer?
- jnz xit_in_stat ; Yes, continue
- mov ah,00000011b ; No, set busy & done
- jmp done ; We're done
-
- xit_in_stat:
- jmp exit ; Normal exit code
- input_status endp
-
- page
- ;***********************************************************
- ;** Flush Input Buffer **
- ;***********************************************************
- input_flush proc near
- mov cs:word ptr rq_head,0 ; Head = 0
- mov cs:word ptr rq_tail,0 ; Tail = 0
- mov cs:word ptr rq_len,0 ; make queue length 0
- jmp exit ; Normal exit code
- input_flush endp
-
- page
- ;***********************************************************
- ;** Get Output Status **
- ;***********************************************************
- output_status proc near
- cmp cs:byte ptr t_busy,0 ; Are we busy?
- je xit_out_stat ; No, continue
- mov ah,00000011b ; Set busy & done
- jmp done ; We're done
-
- xit_out_stat:
- jmp exit ; Normal exit code
- output_status endp
-
- page
- ;***********************************************************
- ;** Read Routine **
- ;** **
- ;** ES:DI contain xfer adrs on entry **
- ;** CX contains num chars requested **
- ;***********************************************************
- read proc near
- cmp cs:byte ptr key_in,0 ; Look for keyboard input?
- jz read_0 ; No, skip
-
- push cx
- push di
- call k_ready ; Is a char waiting?
- pop di
- pop cx
- jz read_0 ; No, skip
-
- mov cx,1
- call update_count
- push di
- call k_read ; Get char from keyboard
- pop di
-
- stosb
- jmp exit ; We're done
-
- read_0:
- mov ax,cs:word ptr rq_len ; Any chars in recv buffer?
- or ax,ax
- jnz read_1 ; Yes, continue
- xor cx,cx ; No, return 0 chars received
- call update_count
- jmp exit ; We're done
-
- read_1:
- ; figure out how many chars to get
- cmp ax,cx ; More than DOS buffer?
- jg read_2 ; Yes, CX already has count
- mov cx,ax ; No, only send what we have
-
- read_2:
- call update_count ; update chars received
- mov bx,offset rqueue ; Get queue ptr
- mov dx,cs:word ptr rq_tail
- read_3:
- add bx,dx ; point at char
- mov al,byte ptr[bx] ; al now has char
-
- cmp cs:byte ptr echo_in,0 ; Echo input on?
- jz not_echo_in ; No, skip
- int fast_write ; Yes, echo to console
- not_echo_in:
-
- stosb ; store char in buffer
- inc dx
- and dx,recv_limit ; wrap if >= limit
- mov cs:word ptr rq_tail,dx ; update tail
- dec cs:word ptr rq_len ; Adjust queue length
- loop read_3 ; Loop again
-
- ; reset busy if we can
- cmp cs:word ptr rq_len,not_busy_len ; Room for more chars?
- jg read_4 ; No, skip
- mov cs:byte ptr r_busy,0 ; Yes, reset busy
- call send_xon ; Send XON char if needed
- read_4:
-
- jmp exit
- read endp
-
- page
- ;***********************************************************
- ;** Write I/O Control Channel **
- ;** **
- ;** ES:DI contain xfer adrs on entry **
- ;** CX contains count **
- ;***********************************************************
- ioctl_out proc near
- push es ; Move pointer to DS:SI
- pop ds
- mov si,di
-
- cmp cx,2 ; Is it a DCW?
- je ioo_1 ; Yes, continue
- cmp cx,1 ; Is it a CSB?
- jz ioo_nc0 ; Yes, continue
- jmp exit ; No, exit
-
- ioo_nc0:
- lodsb ; Yes, get the byte
-
- push cs ; DS = CS
- pop ds
-
- mov ah,al ; Update echo output
- and ah,00100000b
- mov echo_out,ah
-
- mov ah,al ; Update echo input
- and ah,01000000b
- mov echo_in,ah
-
- mov ah,al ; Update keyboard input
- and ah,10000000b
- mov key_in,ah
-
- mov ah,al ; Update DCW/LEN mode
- and ah,00000100b
- mov dcw_len,ah
-
- test al,00000001b ; Drop RS232 signals?
- jnz ioo_nc1 ; No, skip
- call de_init ; Yes, disconnect
- mov byte ptr dcw_len,0 ; Reset to DCW mode
- ioo_nc1:
-
- test al,00000010b ; Flush input buffer?
- jz ioo_nc2 ; No, skip
- jmp input_flush ; Yes, go flush it
- ioo_nc2:
-
- jmp exit ; exit
- ioo_1:
- lodsw ; get DCW in AX
-
- ; make ds = cs
- push cs
- pop ds
-
- ; check for serial device
- test ah,80h ; Serial device?
- jnz ioo_2 ; Yes, continue
- jmp exit ; No, exit
- ioo_2:
-
- call set_dcw ; Go set DCW
-
- mov word ptr dcw,ax ; Save new DCW
- call init_comm ; init comm chip
- jmp exit
-
- ioctl_out endp
-
- page
- ;***********************************************************
- ;** Read I/O Control Channel **
- ;** **
- ;** ES:DI contain xfer adrs on entry **
- ;***********************************************************
- ioctl_in proc near
- cmp cx,2 ; Is it a word?
- je is_2byte ; Yes, go get it
- cmp cx,1 ; Is it a byte?
- jne ioi_xit ; No, exit
-
- xor al,al ; Clear status byte
- or al,cs:byte ptr m_stat ; Update current modem status
- or al,cs:echo_out ; Update echo output
- or al,cs:echo_in ; Update echo input
- or al,cs:key_in ; Update keyboard input
- stosb ; and pass it to DOS
- jmp exit
-
- is_2byte:
- cmp cs:byte ptr dcw_len,0 ; DCW mode?
- jz ioi_1 ; Yes, get DCW
-
- mov ax,cs:rq_len ; No, get receive queue length
- jmp short ioi_2
-
- ioi_1:
- mov ax,cs:dcw ; Get DCW
- ioi_2:
- stosw ; and pass it to DOS
-
- ioi_xit:
- jmp exit
- ioctl_in endp
-
- page
- ;***********************************************************
- ;** Return Number of Chars Processed **
- ;** **
- ;** CX contains number of characters processed **
- ;***********************************************************
- update_count proc near
- push ds
- push bx
-
- lds bx,cs:[ptrsav] ;get pointer to i/o packet
- mov word ptr ds:[bx].count,cx ;cx = count
-
- pop bx
- pop ds
- ret
- update_count endp
-